#pragma once

#include "zen_vap_helper.h"
#include "zen_vap_node.h"
#include "zen_vap_texture.h"
#include "zen_point.h"
#include <vector>
#include <mutex>

namespace Zen { namespace Vap {

	struct Mesh
	{
		std::vector<Vec3> coords;
		std::vector<Vec2> tex_coords;
		std::vector<Color4f> colors;
		std::vector<uint32_t> indexes;
		bool is_strip = false;
		
	};

	using SharedMesh = std::shared_ptr<Mesh>;

	class MeshLoader {
	public:
		static MeshLoader * Get();

		enum class CubeType {
			NoTexture, Colored, Sameface, Apart,
		};
		/// mesh of cube:
		/// has 24 vertexes, 36 indexes
		/// = 6 faces, each face has 4 vertexes, 2 triangles( 6 indexes )
		/// faces order: （RHS） z+, z-, x-, x+, y-, y+ (also front, back, left, right, bottom, top)

		/// createMeshCube...
		/// @arg r : half of edge length.
		SharedMesh createMeshCubeNoBind(float r = 0.5f);

		SharedMesh createMeshCubeColored(float r = 0.5f);

		SharedMesh createMeshCubeSameface(float r = 0.5f);

		/**
		 Skybox
		 (T:top, L:left, F:front, R:right, K:back, B:bottom)
		 if compressed == false. the texture looks like this:
		 	|0T00|
		 	|LFRK|
		 	|0B00|
		 if true. (RKL was rotated 90deg clockwise)
		 	|T R|
		 	|F K|
		 	|B L|
		 */
		SharedMesh createMeshCubeSkybox(float r = 0.5f, bool compressed = false);

	protected:
		MeshLoader();
	};

	class MeshesCache : protected Cache<std::string, SharedMesh>
	{
	public:
		typedef std::string MeshName;
	public:
		static MeshesCache * Get();

		void cacheMesh(MeshName const & name, SharedMesh mesh) { cache(name, mesh); }

		SharedMesh getMesh(MeshName const & name) { return load(name); }

		void clearCachedMeshes(bool include_used = false) { clearCache(include_used); }
		
	protected:
		std::map<MeshName, SharedMesh> m_meshes_cache;

		SharedMesh onCacheNotFound(std::string const &key) override {
			return nullptr;
		}
	};
}}
